package com.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.util.BooleanUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.dto.ConDTO;
import com.dto.ConstructionInformationDTO;
import com.entity.ConstructionInformation;
import com.mapper.ConstructionInformationMapper;
import com.service.ConstructionInformationService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.util.DateTimeFormatterUtil;
import com.util.ObjectINullUtil;
import com.util.UploadPicUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.time.Duration;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;

import static com.constant.RedisConstant.*;

/**
 * <p>
 * 施工信息表 服务实现类
 * </p>
 *
 * @author 马磊
 * @since 2023-02-10
 */
@Service
public class ConstructionInformationServiceImpl extends ServiceImpl<ConstructionInformationMapper, ConstructionInformation> implements ConstructionInformationService {

    @Autowired
    private StringRedisTemplate redisTemplate;

    /**
     * 上传图片
     * @param file
     * @return
     */
    @Override
    public String upload(MultipartFile file) {
        return UploadPicUtils.uploadPicture(file);
    }

    /**
     * 上报信息
     * @param con
     * @return
     */
    @Override
    public String add(ConstructionInformation con) throws IllegalAccessException {
        boolean check = ObjectINullUtil.checkFieldAllNull(con);
        if (check){
            return "fail";
        }
        save(con);
        return "ok";
    }

    /**
     * 查询信息
     * @param userId
     * @param type
     * @return
     */
    @Override
    public List<ConDTO> getInfo(String userId, Integer type) {
        if (StrUtil.isEmpty(userId) || type==null){
            return null;
        }
        LambdaQueryWrapper<ConstructionInformation> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(true,ConstructionInformation::getUid,userId);
        wrapper.eq(true,ConstructionInformation::getType,type);
        List<ConstructionInformation> list = list(wrapper);
        ArrayList<ConDTO> conDTOList = new ArrayList<>();
        list.forEach(con->{
            String content = StrUtil.join("-", con.getRoadName(), con.getStartNumber(), con.getEndNumber(), con.getPlace());
            conDTOList.add(new ConDTO(con.getId(), con.getType(), con.getRouteName(), content));
        });
        return conDTOList;

    }

    /**
     * 根据id查询详情信息
     * @param id
     * @return
     */
    @Override
    public ConstructionInformationDTO selectById(Integer id) {
        if (id==null){
            return null;
        }
        String json = redisTemplate.opsForValue().get(CON_INFO + id);
        if (StrUtil.isNotBlank(json)){
            ConstructionInformationDTO dto = JSONUtil.toBean(json, ConstructionInformationDTO.class);
            return dto;
        }
        if (json!=null){
            return null;
        }
        ConstructionInformationDTO conDTO;
        try {
            boolean b = tryLock(MUTEX + id);
            if (!b){
                selectById(id);
            }
            ConstructionInformation con = getById(id);
            if (con==null){
                redisTemplate.opsForValue().set(DATA_DICTIONARY + id,"",Duration.ofMinutes(NULL_TIME));
                return null;
            }
            conDTO = BeanUtil.copyProperties(con, ConstructionInformationDTO.class);
            //时间格式化
            conDTO.setStartTime(DateTimeFormatterUtil.formatter(con.getStartTime()));
            conDTO.setRestoreTime(DateTimeFormatterUtil.formatter(con.getRestoreTime()));
            //处理图片
            if (StrUtil.isNotEmpty(con.getImgList())){
                conDTO.setPicList(con.getImgList().split(","));
            }
            redisTemplate.opsForValue().set(CON_INFO + id,JSONUtil.toJsonStr(con),Duration.ofMinutes(CON_INFO_TIME));
        } finally {
            unlock(MUTEX + id);
        }
        return conDTO;
    }

    /**
     * 获得锁
     * @param key
     * @return
     */
    private boolean tryLock(String key) {
        Boolean flag = redisTemplate.opsForValue().setIfAbsent(key, "2", Duration.ofSeconds(MUTEX_TIME));
        return BooleanUtil.isTrue(flag);
    }

    /**
     * 释放锁
     * @param key
     */
    private void unlock(String key) {
        redisTemplate.delete(key);
    }
}
